/**
 * Represents the memory of the CSE7000 machine. Modeled as an array of Registers.<br><br>
 * @author Dan Carpenter
 * Change Log:<br>
 *  - 05/22/09 - Meghan Day<br>
 *  	- Created skeleton<br><br>
 *  - 05/25/09 - Dan Carpenter<br>
 *  	- Filled in constructor, setValue, getValue, and getOpCode.<br><br>
 *  - 05/26/09 - Dan Carpenter<br>
 * 		- Fixed the constructor to initialize each register to a 32 bit word<br><br>
 * 	- 05/26/09 - Meghan Day<br>
 * 		- Moved getOpCode to Register class.<br><br>
 *  - 05/28/09 - Meghan Day<br>
 *  	- Added get methods that call through to register.<br><Br>
 *  - 06/02/09 - Sam Jones<br>
 *  	- Fixed javadoc.<br><br>
 *  - 06/03/09 - Meghan Day<br>
 *  	- Checks that index is in bounds before calling.
 */
public class Memory {

	/** Array of registers for storing memory 
	 */
	private Register mem[];
	private int number;
	private int size;
	
	/**
	 * Two-argument constructor that creates a Memory object with the the number of words
	 * and size of words provided.
	 * @param wordNumber Number of words to store in memory.
	 * @param wordSize Size of each word to store in memory.
	 */
	public Memory(int wordNumber, int wordSize){
		number = wordNumber;
		size = wordSize;
		mem = new Register[number];
		for(int count = 0; count < number; count++) {
			mem[count] = new Register(size);
		}
	}
	
	/**
	 * Sets the word at the specified location in memory.
	 * @param index Location in memory to set. 
	 * @param value Value to set in memory.
	 */
	public void setValue(int index, int value){
		if ((index >= 0) && (index < number)) {
			mem[index].setValue(value);
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
		}
	}
	
	/**
	 * Gets the word at the specified location in memory.
	 * @param index Location in memory to retrieve value.
	 */
	public int getValue(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getValue();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the opcode, or first eight bits, of the value at the location in memory.
	 * @param index Location in memory to retrieve op-code.
	 * @return The opcode as an integer
	 */
	public int getOpCode(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getOpCode();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the address field, or the last sixteen bits, of the value at the location
	 * in memory.
	 * @param index Location in memory to retrieve address field.
	 * @return The address as an integer
	 */
	public int getAddressField(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getAddressField();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the XR field at the location in memory.
	 * @param index Location in memory to retrieve XR field.
	 * @return The value of the XR field
	 */
	public int getXR(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getXR();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the debug bit at the location in memory.
	 * @param index Location in memory to retrieve debug field.
	 * @return The value of the debug bit
	 */
	public int getDebug(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getDebug();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the IOWD flag at the location in memory.
	 * @param index Location in memory to retrieve IOWD field.
	 * @return The value of the IOWD flag
	 */
	public int getIOWDFlag(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getIOWDFlag();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
	
	/**
	 * Gets the address flag field bits at the location in memory.
	 * @param index Location in memory to retrieve address flag field.
	 * @return The value of the address field
	 */
	public int getAddrFlag(int index){
		if ((index >= 0) && (index < number)) {
			return mem[index].getAddrFlag();
		}
		else {
			System.out.println("Error. Invalid location in memory: " + index);
			return 0;
		}
	}
}
